import threading
from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
import json
import os

import websocket
import oss2
import uuid
from datetime import datetime, timedelta
import edge_tts
import asyncio
import tempfile
from pathlib import Path
import requests
import hashlib
import time
from .models.wechat_user import WechatUser
from .models.audio import Audio
from decouple import config
from django.utils import timezone
from .models.audio import AudioUsage
from .logic.wechat import WechatLogic
from .models.vip import VipMember
from api.utils.response import success_response, error_response

def get_oss_client():
    auth = oss2.Auth(settings.OSS_ACCESS_KEY_ID, settings.OSS_ACCESS_KEY_SECRET)
    bucket = oss2.Bucket(auth, settings.OSS_ENDPOINT, settings.OSS_BUCKET_NAME)
    return bucket

def save_audio_file(file_path, file_name, file_content):
    """保存音频文件到指定位置"""
    if settings.AUDIO_STORAGE_TYPE == 'oss':
        # 上传到阿里云OSS
        bucket = get_oss_client()
        with open(file_path, 'rb') as f:
            bucket.put_object(file_name, f)
        url = f"https://{settings.OSS_BUCKET_NAME}.{settings.OSS_ENDPOINT}/{file_name}"
    else:
        # 保存到本地
        local_path = os.path.join(settings.LOCAL_AUDIO_ROOT, file_name)
        os.makedirs(os.path.dirname(local_path), exist_ok=True)
        with open(local_path, 'wb') as f:
            f.write(file_content)
        
        # domain_port = config('DOMAIN_PORT', default='8001')
        url = f"{settings.LOCAL_AUDIO_URL}{file_name}"
    return url
def send_progress_message(message):
    """
    发送进度消息到WebSocket服务器
    """
    try:
        ws = websocket.WebSocket()
        ws.connect(f"wss://crmeb.tietaozhe.com/ws")
        ws.send(json.dumps(message))
        ws.close()
    except Exception as e:
        print(f"发送WebSocket消息失败: {str(e)}")
# 文字转语音
@csrf_exempt
def audio_create(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            text = data.get('text', '')
            voice = data.get('voice', 'zh-CN-XiaoxiaoNeural')
            rate = data.get('rate', '+0%')
            volume = data.get('volume', '+0%')
            style = data.get('style', '')
            style_degree = data.get('style_degree', 1.0)

            # 获取用户信息
            wechat_logic = WechatLogic()
            token = request.headers.get('Authorization')
            if not token:
                return error_response(message='未提供认证令牌',code=401)
            
            user = wechat_logic.get_user_by_token(token)
            if not user:
                return error_response(message='未登录或登录已过期',code=401)
            # 检查用户是否有正在处理的音频
            processing_audio = Audio.objects.filter(
                user=user,
                status__in=['pending', 'processing']
            ).first()

            if processing_audio:
                return error_response({
                    'message': '您有正在处理的音频，请等待处理完成后再试或在【我的-配音历史】删除记录',
                    'code': 400,
                    'data': {
                        'id': processing_audio.id,
                        'status': processing_audio.status,
                        'status_text': {
                            'pending': '等待处理',
                            'processing': '处理中',
                            'completed': '已完成',
                            'failed': '处理失败'
                        }.get(processing_audio.status, '未知状态')
                    }
                })
            # 检查用户是否是VIP会员
            try:
                vip_member = VipMember.objects.get(user=user)
                is_vip = vip_member.is_active and vip_member.check_vip_status()
            except VipMember.DoesNotExist:
                is_vip = False
            
            # 检查文本长度限制
            text_length = len(text)
            if not is_vip and text_length > 500:
                return error_response(message='免费用户单次合成字符数不能超过500字',code=403)
            
            # 检查每日使用次数限制
            today = timezone.now().date()
            
            # 获取或创建用户今日使用记录
            usage, created = AudioUsage.objects.get_or_create(
                user=user,
                date=today,
                defaults={'total_chars': 0, 'total_count': 0}
            )
            
            # 检查免费用户每日使用次数限制
            if not is_vip and usage.total_count >= 10:
                return error_response(message='免费用户每日合成次数不能超过10次',code=403)
            if not text:
                return error_response(message='文本内容不能为空',code=400)

            # 创建临时文件
            with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as temp_file:
                temp_path = temp_file.name
            # 生成文件名
            file_name = f"tts/{datetime.now().strftime('%Y%m%d')}/{uuid.uuid4()}.mp3"
            # 创建数据库记录
            audio = Audio.objects.create(
                title=f"语音_{datetime.now().strftime('%Y%m%d%H%M%S')}",
                text=text,
                voice=voice,
                rate=rate,
                file_name=file_name,
                url="",  # 初始为空，异步任务完成后更新
                user=user,
                status='pending',  # 添加状态字段，表示正在处理中
                volume=volume
            )
            
            # 使用edge-tts生成音频
            async def generate_audio():
                communicate = edge_tts.Communicate(text, voice, rate=rate, volume=volume)
                print(f"开始生成音频，文本长度: {len(text)} 字符")
                print(f"使用语音: {voice}, 语速: {rate}, 音量: {volume}")
                
                total_bytes = 0
                last_progress = 0
                
                with open(temp_path, 'wb') as f:
                    async for chunk in communicate.stream():
                        if chunk["type"] == "audio":
                            f.write(chunk["data"])
                            total_bytes += len(chunk["data"])
                            # 计算进度百分比
                            progress = min(100, (total_bytes / 1024 / 1024) * 100)
                            if progress - last_progress >= 1:  # 每1%更新一次
                                # print(f"生成进度: {progress:.1f}% ({total_bytes:,} 字节)")
                                if is_async:
                                    send_progress_message({
                                        'type': 'progress',
                                        'to_uid': audio.user.id,
                                        'audio_id': audio.id,
                                        'status': 'processing',
                                        'total_paragraphs': 100,
                                        'current_paragraph': progress,
                                        'total_sentences': 0,
                                        'current_sentence': 0,
                                        'message': f"生成进度: {progress:.1f}% ({total_bytes:,} 字节)"
                                    })
                                last_progress = progress
                        elif chunk["type"] == "WordBoundary":
                            # 计算文本处理进度
                            text_progress = min(100, (chunk['offset'] / len(text)) * 100)
                            # print(f"文本处理进度: {text_progress:.1f}% ({chunk['offset']}/{len(text)} 字符)")
                
                print(f"音频文件保存完成，总大小: {total_bytes:,} 字节")
                return total_bytes

            # 使用线程进行异步处理
            def process_audio():
                try:
                    # 更新状态为处理中
                    audio.status = 'processing'
                    audio.save()
                    
                    # 运行异步函数
                    total_bytes = asyncio.run(generate_audio())
                    
                    # 读取临时文件内容
                    with open(temp_path, 'rb') as f:
                        file_content = f.read()

                    # 保存文件
                    url = save_audio_file(None, file_name, file_content)

                    # 删除临时文件
                    os.unlink(temp_path)

                    # 更新音频记录
                    audio.status = 'completed'
                    audio.url = url
                    audio.save()
                    send_progress_message({
                        'to_uid': audio.user.id,
                        'type': 'progress',
                        'audio_id': audio.id,
                        'status': 'completed',
                        'message': f'音频生成完成',
                        'url': f"{domain_name}{audio.url}"
                    })
                    # 更新用户使用记录
                    if not is_vip:
                        usage.total_chars += text_length
                        usage.total_count += 1
                        usage.save()
                        
                except Exception as e:
                    print(f"处理音频时出错: {str(e)}")
                    # 更新音频记录状态为失败
                    audio.status = 'failed'
                    audio.save()

            # 检查是否使用异步模式
            is_async = data.get('async', True)  # 默认为同步模式
            
            if is_async:
                # 异步模式：启动后台线程处理
                thread = threading.Thread(target=process_audio)
                thread.daemon = True  # 设置为守护线程，主线程结束时自动结束
                thread.start()

                # 返回任务ID和状态
                domain_name = config('DOMAIN_NAME', default='192.168.220.131')
                return success_response(
                    message='音频正在异步生成中，请稍后在配音历史查询结果',
                    data={
                        'id': audio.id,
                        'title': audio.title,
                        'text': audio.text,
                        'voice': audio.voice,
                        'rate': audio.rate,
                        'file_name': audio.file_name,
                        'status': 'pending',
                        'usage': {
                            'total_chars': usage.total_chars,
                            'total_count': usage.total_count,
                            'is_vip': is_vip,
                            'daily_limit': 10 if not is_vip else None,
                            'chars_limit': 500 if not is_vip else 5000
                        }
                    }
                )
            else:
                # 同步模式：直接处理
                try:
                    # 更新状态为处理中
                    audio.status = 'processing'
                    audio.save()
                    
                    # 运行异步函数
                    total_bytes = asyncio.run(generate_audio())
                    
                    # 读取临时文件内容
                    with open(temp_path, 'rb') as f:
                        file_content = f.read()

                    # 保存文件
                    url = save_audio_file(None, file_name, file_content)

                    # 删除临时文件
                    os.unlink(temp_path)

                    # 更新音频记录
                    audio.status = 'completed'
                    audio.url = url
                    audio.save()
                    
                    # 更新用户使用记录
                    if not is_vip:
                        usage.total_chars += text_length
                        usage.total_count += 1
                        usage.save()

                    # 使用环境变量中的域名配置
                    domain_name = config('DOMAIN_NAME', default='192.168.220.131')
                    
                    return success_response(
                        message='音频创建成功',
                        data={
                            'id': audio.id,
                            'title': audio.title,
                            'text': audio.text,
                            'voice': audio.voice,
                            'rate': audio.rate,
                            'volume': audio.volume,
                            'style': audio.style,
                            'style_degree': audio.style_degree,
                            'file_name': audio.file_name,
                            'url': f"{domain_name}{audio.url}",
                            'status': 'completed',
                            'created_at': audio.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                            'usage': {
                                'total_chars': usage.total_chars,
                                'total_count': usage.total_count,
                                'is_vip': is_vip,
                                'daily_limit': 10 if not is_vip else None,
                                'chars_limit': 500 if not is_vip else 5000
                            }
                        }
                    )
                except Exception as e:
                    # 更新音频记录状态为失败
                    audio.status = 'failed'
                    audio.save()
                    return error_response(message=f'音频创建失败：{str(e)}',code=500)
        except json.JSONDecodeError:
            return error_response(message='无效的JSON数据',code=400)
        except Exception as e:
            return error_response(message=f'音频创建失败：{str(e)}',code=500)
    else:
        return error_response(message='仅支持POST请求',code=405)

# 上传音频
@csrf_exempt
def audio_upload(request):
    if request.method == 'POST':
        try:
            if 'audio' not in request.FILES:
                return error_response(message='没有找到音频文件',code=400)

            audio_file = request.FILES['audio']
            
            if audio_file.content_type not in settings.ALLOWED_AUDIO_TYPES:
                return error_response(message='不支持的文件类型',code=400)

            if audio_file.size > settings.MAX_AUDIO_SIZE:
                return error_response(message='文件大小超过限制',code=400)

            # 生成唯一的文件名
            file_ext = os.path.splitext(audio_file.name)[1]
            file_name = f"upload/{datetime.now().strftime('%Y%m%d')}/{uuid.uuid4()}{file_ext}"

            # 保存文件
            url = save_audio_file(None, file_name, audio_file.read())

            return success_response(
                message='音频上传成功',
                data={
                    'file_name': file_name,
                    'url': url,
                    'size': audio_file.size,
                    'content_type': audio_file.content_type
                }
            )

        except Exception as e:
            return error_response(message=f'上传失败：{str(e)}',code=500)
    else:
        return error_response(message='仅支持POST请求',code=405)


